package org.september.pisces.led.service.shizhan;


import org.september.pisces.led.entity.LedArea;
import org.september.pisces.led.entity.LedFlash;
import org.september.pisces.led.service.LEDManager;
import org.september.pisces.led.service.LedColorEnum;
import lombok.extern.slf4j.Slf4j;

import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Default
 */
@Slf4j
public class ShiZhanLEDManager implements LEDManager {

    private final MyUdpSocket my_udp;
    private final String ledhost;
    private final int ledPort;
    private final static LEDSender2010 ledsender = new LEDSender2010();
    static Map<String, Integer> alignMap = new HashMap<>();

    static {
        alignMap.put("left", LEDSender2010.ALIGN_LEFT);
        alignMap.put("center", LEDSender2010.ALIGN_CENTER);
        alignMap.put("right", LEDSender2010.ALIGN_RIGHT);
        alignMap.put("top", LEDSender2010.ALIGN_TOP);
        alignMap.put("bottom", LEDSender2010.ALIGN_BOTTOM);
    }

    public ShiZhanLEDManager(MyUdpSocket my_udp, String ledhost, int ledPort) {
        this.my_udp = my_udp;
        this.ledhost = ledhost;
        this.ledPort = ledPort;
    }

    public boolean send_data() {
        synchronized (ledsender) {
            try {
                int size = 0;
                byte[] packet = new byte[1280];
                int i, j, k, x, r;
                int tx, tx_repeat = 5;
                boolean ok;
                //下面为通讯代码，包括数据的拆分打包、发送
                //    由于是UDP通讯，增加

                //如果数据量大于
                if (ledsender.GetDataSize() > (1 << 21)) {
                	log.warn("发送情报板" + this.ledhost + "异常");
                    return false;
                }

                ledsender.Compress();

                //起始包
                ok = false;
                for (tx = 0; tx < tx_repeat; tx++) {
                    size = ledsender.pkg_begin(packet, 0);
                    udp_send(packet, size);
                    for (x = 0; x < 50; x++) {
                        size = udp_receive(packet);
                        if (size > 0 && ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_BEGIN, 0) > 0) {
                            ok = true;
                            break;
                        }
                    }
                    if (ok) break;
                }
                if (!ok) {
                	log.warn("发送情报板" + this.ledhost + "异常2");
                    return false;
                }

                //数据包
                k = ledsender.get_pkg_count(512);
                i = 1;
                while (i <= k) {
                    ok = false;
                    for (tx = 0; tx < tx_repeat; tx++) {
                        j = i;
                        size = ledsender.pkg_data(packet, 0, i, 512);
                        udp_send(packet, size);
                        for (x = 0; x < 50; x++) {
                            size = udp_receive(packet);
                            if (size > 0) {
                                r = ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_DATA, i);
                                switch (r) {
                                    case 0x1:
                                        ok = true;
                                        j = i + 1;
                                        break;
                                    case 0x2:
                                        j = ledsender.fix_serialno;
                                        break;
                                }
                            }
                            if (ok) break;
                        }
                        i = j;
                        if (ok) break;
                    }
                    if (!ok) {
                    	log.warn("发送情报板" + this.ledhost + "异常3");
                        return false;
                    }
                }

                //结束包
                ok = false;
                for (tx = 0; tx < tx_repeat; tx++) {
                    size = ledsender.pkg_end(packet, 0, i);
                    udp_send(packet, size);
                    for (x = 0; x < 50; x++) {
                        size = udp_receive(packet);
                        if (size > 0 && ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_END, i) > 0) {
                            ok = true;
                            break;
                        }
                    }
                    if (ok) break;
                }
                return false;
            } catch (Exception ex) {
                log.warn("发送情报板" + this.ledhost + "失败 " + ex.getMessage());
                return false;
            }
        }
    }

    // 按顺序显示提示节目信息
    public void showFlash(LedFlash ledFlash, Map<String, String> map) {
        List<LedArea> areas = ledFlash.getAreas();
        if (areas.isEmpty()) {
            log.error("该节目无内容");
            return;
        }
        try {
            ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_DOUBLE);
            ledsender.AddChapter(1, 1000);
            ledsender.AddRegion(ledFlash.getX(), ledFlash.getY(), ledFlash.getW(), ledFlash.getH());
            ledsender.AddLeaf(1, 2000);
            int top = 0;
            //目前只算上下叠加
            StringBuilder sb = new StringBuilder();
            for (LedArea area : areas) {
                String content = area.getContent();
                if (map!=null){
                    for (String key : map.keySet()) {
                        content = content.replace(key, map.get(key));
                    }
                }

                sb.append(content);
                String[] strings = content.split("\n");
                int areaTop = top;

                for (String line : strings) {
                    addTextEx(0, areaTop, line, area);
                    areaTop += area.getFontSize() + 4;//4: 文字间距
                }
                top += area.getHeight();
            }
            send_data();
            log.info("发布[" + sb + "]到" + ledhost);
        } catch (Exception ex) {
            log.info("发布信息到" + ledhost + "失败", ex);
        }
    }



    public void addTextEx(int x, int y, String content, LedArea area) {
        ledsender.AddTextEx(x, y, area.getWidth(), area.getHeight(), content, alignMap.get(area.getTextAlign()),
                LEDSender2010.ALIGN_TOP, "宋体", area.getFontSize(), Color.BLACK,
                LedColorEnum.getByName(area.getColor()), 0, 1, 0, 2, 0, 0, 0, 0);
    }


    //发送UDP包，buffer为发送数据，size为发送数据长度
    public void udp_send(byte[] buffer, int size) {
        byte[] packet = new byte[size];
        ledsender.blockCopy(packet, 0, buffer, 0, size);
        ledsender.print_stream(packet, size);
        try {
            my_udp.send(ledhost, ledPort, packet, size);
        } catch (Exception ex) {
            log.error("发送情报板失败", ex);
        }
    }

    //接收UDP包，buffer为接收数据，size为接收数据长度
    public int udp_receive(byte[] buffer) {
        int size = 0;
        size = my_udp.receive();
        if (size > 0) {
            my_udp.get_receive_packet(buffer, size);
        }
        return size;
    }
}
